home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 51329 / 51329.xpi / chrome / firefound.jar / content / geolocation.js < prev    next >
Text File  |  2009-12-14  |  5KB  |  195 lines

  1. /**
  2.  * Geolocation object to fill in for Firefox's broken geolocation support
  3.  * for extensions.
  4.  *
  5.  * Contacts Google's geolocation service, which uses a list of WiFi access
  6.  * points and IP address to geolocate.
  7.  *
  8.  * @author chris
  9.  */
  10.  
  11. var GEOLOCATION = {
  12.     ERROR_WIFI_NOT_AVAILABLE : -2147221231,
  13.     
  14.     /**
  15.      * The cached last position.
  16.      */
  17.     _lastPosition : null,
  18.     
  19.     /**
  20.      * Making the last position readonly from outside of the object.
  21.      */
  22.     get lastPosition() { return this._lastPosition; },
  23.     set lastPosition() { throw Exception; },
  24.     
  25.     /**
  26.      * @var hash
  27.      * A list of callbacks that have registered with the geolocation service
  28.      * to get notifications of new locations.
  29.      */
  30.     listeners : {},
  31.     
  32.     /**
  33.      * Service initializer.  Uses Firefox 3.5's wifi monitoring to determine change in location.
  34.      */
  35.     load : function () {
  36.         var wifi_service = Components.classes["@mozilla.org/wifi/monitor;1"].getService(Components.interfaces.nsIWifiMonitor);
  37.         wifi_service.startWatching(this);
  38.     },
  39.     
  40.     /**
  41.      * Service unloader.  Cleans up after the initializer.
  42.      */
  43.     unload : function () {
  44.         var wifi_service = Components.classes["@mozilla.org/wifi/monitor;1"].getService(Components.interfaces.nsIWifiMonitor);
  45.         wifi_service.stopWatching(this);
  46.     },
  47.     
  48.     /**
  49.      * The callback function for the wifi listener.
  50.      *
  51.      * @param array accessPoints A list of WiFi access ponts.
  52.      */
  53.     onChange : function (accessPoints) {
  54.         // Contact the Geolocation service and get the new coordinates.
  55.         var _length = accessPoints.length;
  56.         
  57.         // The JSON request for the geolocation service.
  58.         var request_body = {
  59.             version: "1.1.0",
  60.             host: "firefound.com",
  61.             request_address: true
  62.         };
  63.         
  64.         request_body.wifi_towers = [];
  65.         
  66.         if (_length > 0) {
  67.             for (var i = 0; i < _length; i++) {
  68.                 // Include each wifi access point and its strength.
  69.                 request_body.wifi_towers.push(
  70.                     {
  71.                         "mac_address" : accessPoints[i].mac,
  72.                         "signal_strength": accessPoints[i].signal,
  73.                         "age": 0,
  74.                         "ssid": accessPoints[i].ssid
  75.                     }
  76.                 );
  77.             }
  78.         }
  79.         
  80.         // Ask Google for the geophysical location.
  81.         var req = new XMLHttpRequest();
  82.         req.open("POST", "http://www.google.com/loc/json", true);
  83.         var self = this;
  84.         
  85.         req.onreadystatechange = function () {
  86.             if (req.readyState == 4) {
  87.                 if (FIREFOUND.prefs.getBoolPref("debug")) {
  88.                     FIREFOUND.log("onChange: " + req.responseText);
  89.                 }
  90.                 
  91.                 var json = JSON.parse(req.responseText);
  92.                 
  93.                 if ("location" in json) {
  94.                     // Save this location for easy, painless access.
  95.                     self._lastPosition = json.location;
  96.                     self._lastPosition.wifi_towers = request_body.wifi_towers;
  97.                     
  98.                     for (listener in self.listeners) {
  99.                         // Notify all the listeners of a new location.
  100.                         self.listeners[listener].success(self._lastPosition);
  101.                     }
  102.                 }
  103.                 else {
  104.                     self.log("No location could be determined.");
  105.                 }
  106.             }
  107.         };
  108.         
  109.         req.send(JSON.stringify(request_body));
  110.     },
  111.     
  112.     /**
  113.      * Error callback for the WiFi listener.  Not a big deal (unless it errors over and over).
  114.      */ 
  115.     onError : function (value) {
  116.         if (value == GEOLOCATION.ERROR_WIFI_NOT_AVAILABLE) {
  117.             // User does not have WiFi interface.
  118.             // Just use the IP address.
  119.             this.onChange([]);
  120.         }
  121.         else {
  122.             this.log("WiFi Listener Error: " + value);
  123.         }
  124.     },
  125.     
  126.     QueryInterface: function(iid) {  
  127.         if (iid.equals(Components.interfaces.nsIWifiListener) ||  
  128.             iid.equals(Components.interfaces.nsISupports)) {
  129.             return this;
  130.         }
  131.         
  132.         throw Components.results.NS_ERROR_NO_INTERFACE;
  133.     },
  134.     
  135.     /**
  136.      * Public interface to the geolocation service.
  137.      * 
  138.      * @param function The success callback.
  139.      * @param function The error callback.
  140.      * @param options Unused.
  141.      */
  142.     
  143.     getCurrentPosition : function (successCallback, errorCallback, options) {
  144.         if (this.lastPosition) {
  145.             successCallback(this.lastPosition);
  146.         }
  147.         else {
  148.             // An unlikely scenario, since the WIFI onchange will be called as soon as the service starts.
  149.             // TODO Fetch the current access points and get the location.
  150.             errorCallback("lastPosition is undefined");
  151.         }
  152.     },
  153.     
  154.     /**
  155.      * Allows objects to register for notifications of position changes.
  156.      *
  157.      * @param function The success callback.
  158.      * @param function The error callback.
  159.      * @param options Unused.
  160.      */
  161.     watchPosition : function (successCallback, errorCallback, options) {
  162.         // Use the current microtime as the id of the watcher.
  163.         var watchId = new Date().getTime();
  164.         
  165.         this.listeners[watchId] = { success: successCallback, errors: errorCallback };
  166.         
  167.         return watchId;
  168.     },
  169.     
  170.     /**
  171.      * Removes a listener from the position change notification list.
  172.      *
  173.      * @param string The id of the listener.
  174.      */
  175.     
  176.     clearWatch : function (watchId) {
  177.         if (watchId in this.listeners) {
  178.             delete this.listeners[watchId];
  179.         }
  180.     },
  181.     
  182.     /**
  183.      * Log a message to the Error Console.
  184.      *
  185.      * @param string message
  186.      */
  187.     log : function (message) {
  188.         var consoleService = Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService);
  189.         consoleService.logStringMessage("GEOLOCATION: " + message);
  190.     }
  191. };
  192.  
  193. // Automatically load this service when it's included.
  194. addEventListener("load", function () { GEOLOCATION.load(); }, false);
  195. addEventListener("unload", function () { GEOLOCATION.unload(); }, false);